<script lang="ts" setup>
  import { reactive, ref, unref, Ref, toRaw } from 'vue';
  import { PlusOutlined, DownloadOutlined } from '@ant-design/icons-vue';
  import { useMessage } from '/@/hooks/web/useMessage';
  import AddOrgModal from './AddOrgModal.vue';
  import PickOrgModal from './PickOrgModal.vue';
  import { getOrgList, deleteOrg, updateOrgResource } from '/@/api/organization';
  import { useUserStore } from '/@/store/modules/user';
  import { Icon } from '/@/components/Icon';
  import { cloneDeep } from 'lodash';

  const { createMessage } = useMessage();
  const userStore = useUserStore();
  const appInfo = userStore.getLoginApp;
  const ifSubManager = appInfo.clientManagerFlag == 1;
  const appAutoFlag = appInfo.accessableList.filter((e) => e.clientId == appInfo.currentId)[0]
    .autoFlag;
  const state = reactive({
    loading: false,
  });

  const searchFormRef = ref();
  const searchForm = reactive({ orgName: '', orgNo: '' });
  const formatTreeData = <T>(s, cf): T[] | undefined => {
    function trans(s) {
      if (!s || !s.length) return undefined;
      let t: T[] = [];
      s.forEach((e) => {
        t.push({ ...cf(e, trans) });
      });
      return t;
    }
    return trans(s);
  };

  const searchFormActions = {
    onSearch() {
      tableActions.getList();
    },
    resetFields(formRef) {
      formRef.resetFields();
      tableActions.getList();
    },
  };

  const table = reactive({
    selected: [] as any,
  });

  // 表格数据
  const tableData = ref([]) as Ref<any[]>;

  // 懒加载表格ref
  const lazyTableRef = ref();

  // 获取父节点的children
  function getObjById(list, id) {
    if (!(list instanceof Array)) return null;
    for (let i in list) {
      let item = list[i];
      if (item.id === id) return item;
      else {
        if (item._children) {
          let obj = getObjById(item._children, id);
          if (obj) return obj;
        }
      }
    }
  }

  // 点击过的节点数据
  const loadMap = ref(new Map());

  const tableActions = {
    async getList() {
      let params = {
        orgName: searchForm.orgName,
        orgNo: searchForm.orgNo,
        startIndex: pg.current,
        pageSize: pg.size,
      };
      state.loading = true;
      let { data: ret, code, msg } = await getOrgList(params);
      state.loading = false;
      if (code === 200) {
        let result = formatTreeData<any>(JSON.parse(JSON.stringify(ret)), (e, c) => {
          let children = e.children;
          delete e.children;
          return {
            ...e,
            hasChildren: children?.length > 0,
            _children: c(children),
          };
        });
        tableData.value = result || [];
        table.selected = [];
        // pg.total = ret.total;
      } else {
        createMessage({
          message: msg,
          type: 'error',
        });
      }
    },
    selectionChange(v) {
      table.selected = v;
    },
    create() {
      modal.data = undefined;
      modalActions.show();
    },
    update(r) {
      modal.data = r;
      modalActions.show();
      parentIds.oldParentId = r.parentId;
    },
    delete(r) {
      deleteReq([r.id], 1, r);
    },
    batchDel() {
      let ids = table.selected.map((e) => e.id);
      // 把没有刷新过的已选择数据传过去
      let tableSelected = cloneDeep(table.selected);
      deleteReq([...ids], 2, tableSelected);
    },
    importOrg() {
      pickOrgModalActions.show();
    },
    load(row, _treeNode, resolve) {
      // 将获取到的节点数据添加到loadMap变量中
      loadMap.value.set(row.id, { row, _treeNode, resolve });
      resolve(row._children);
    },
    reloadTree(r: any, type?) {
      // 如果不是树形，就不重新刷新
      if (r.parentId == -1 && r.hasChildren == false && !r._children) {
        return;
      }
      // 获取表格ref的数据
      const store = lazyTableRef.value.store;
      // 最新的表格数据
      let scopeTableData = store.states.data.value;
      // 父节点的children
      let parentChildren = getObjById(scopeTableData, r.parentId);

      // 父节点的相关数据
      let rtr = loadMap.value.get(r.parentId);

      // 已经拿到父级id，直接渲染parentId，不用找parentId
      if (type == 'update') {
        parentChildren = getObjById(scopeTableData, parentIds.newParentId);
        rtr = loadMap.value.get(parentIds.newParentId);
        if (!rtr) {
          // 懒加载保存的映射数组。修改该数组的数字可以改变视图
          let lazyData = lazyTableRef.value.store.states.lazyTreeNodeMap.value;
          // 懒加载数组中当前的父节点
          let lazyParent;
          for (const key in lazyData) {
            if (getObjById(lazyData[key], parentIds.newParentId)) {
              lazyParent = getObjById(lazyData[key], parentIds.newParentId);
            }
          }
          // 把最新的数据赋值给懒加载数组
          if (parentChildren.id == lazyParent.id) {
            lazyParent.hasChildren = parentChildren.hasChildren;
            lazyParent._children = parentChildren._children;
          }
          return;
        }
      }
      // 该节点下只有一个节点时，手动清空
      if (!parentChildren._children) {
        lazyTableRef.value.store.states.lazyTreeNodeMap.value[r.parentId] = [];
      } else if (rtr) {
        rtr._treeNode.loading = true;
        // 把最新的父节点的children传给load事件，更新children
        tableActions.load(parentChildren, rtr._treeNode, rtr.resolve);
      }
    },
  };

  const pg = reactive({
    current: 1,
    size: 20,
    total: 0,
  });

  const pgActions = {
    resetPg: () => {
      pg.current = 1;
      pg.size = 20;
      pg.total = 0;
    },
    currentChange(r) {
      pg.current = r;
      searchFormActions.onSearch();
    },
    sizeChange(r) {
      pg.current = 1;
      pg.size = r;
      searchFormActions.onSearch();
    },
  };

  interface IParentIds {
    newParentId: number | undefined;
    oldParentId: number | undefined;
  }
  const parentIds: IParentIds = reactive({
    newParentId: undefined,
    oldParentId: undefined,
  });

  // 弹框类型 新建：false，编辑：true
  const dialogUpdateMode: Ref<boolean> = ref(false);
  const modal = reactive({
    visible: false,
    data: undefined as any,
  });

  const modalActions = {
    async success() {
      pg.current = 1;
      await tableActions.getList();
      // 新建
      if (dialogUpdateMode.value == false) {
        if (parentIds.newParentId !== -1) {
          tableActions.reloadTree(parentIds, 'update');
        }
      }
      // 编辑
      else {
        // 父级不变
        if (parentIds.oldParentId == parentIds.newParentId) {
          // 最外层，不更新load函数
          if (modal.data?.parentId == -1) {
            return;
          } else {
            // 有父级，更新父级load
            tableActions.reloadTree(modal.data);
          }
        }
        // 父级改变
        else {
          // 新父级是最外层，只更新原父级，不更新load函数
          if (parentIds.newParentId == -1) {
            tableActions.reloadTree(modal.data);
          }
          // 新父级不是最外层
          else {
            // 更新新父级
            tableActions.reloadTree(parentIds, 'update');
            // 原父级不是最外层，更新原父级load函数
            if (parentIds.oldParentId !== -1) {
              // 更新原父级
              tableActions.reloadTree(modal.data);
            }
          }
        }
      }
    },
    show() {
      modal.visible = true;
    },
    // 父级id
    getParentId(e: number) {
      parentIds.newParentId = e;
    },
    // 弹框类型
    getUpdateMode(e: boolean) {
      dialogUpdateMode.value = e;
    },
  };

  const pickOrgModal = reactive({
    visible: false,
    data: undefined,
  });

  const pickOrgModalActions = {
    success() {
      pg.current = 1;
      searchFormActions.onSearch();
    },
    show() {
      pickOrgModal.visible = true;
    },
  };

  const modal1 = reactive({
    visible: false,
    data: undefined as any,
  });

  const modal1Actions = {
    show() {
      modal1.visible = true;
    },
    async success(resourceSelected) {
      state.loading = true;
      const { respCode, respMsg } = await updateOrgResource({
        id: modal1.data.id,
        clientManagerIds: resourceSelected,
      });
      state.loading = false;
      if (respCode == 200) {
        createMessage({ message: respMsg });
        await tableActions.getList();
        // 依次获取map对象值并重新渲染节点数据
        for (let key of loadMap.value.keys()) {
          parentIds.newParentId = key;
          tableActions.reloadTree(parentIds, 'update');
        }
      }
    },
  };
  // req
  // type:1删除单条，2批量删除
  async function deleteReq(p, type, data) {
    state.loading = true;
    const { code, msg } = await deleteOrg({ ids: p });
    state.loading = false;
    if (code == 200) {
      createMessage({
        message: msg,
      });
      await tableActions.getList();
      // 删除单条，局部刷新父节点
      if (type == 1) {
        tableActions.reloadTree(data);
      }
      // 批量删除，遍历并局部刷新父节点
      else {
        for (const item of data) {
          tableActions.reloadTree(item);
        }
      }
    }
  }

  searchFormActions.onSearch();
</script>

<template>
  <div class="p-4 menu-management">
    <div class="searchBox px-4 pt-4">
      <el-form label-width="60px" :model="searchForm" ref="searchFormRef" inline>
        <el-form-item prop="orgName" label="机构名称" :label-width="80">
          <el-input placeholder="请输入机构名称" v-model="searchForm.orgName" clearable />
        </el-form-item>
        <el-form-item prop="orgNo" label="机构编号" :label-width="80">
          <el-input placeholder="请输入机构编号" v-model="searchForm.orgNo" clearable />
        </el-form-item>
        <el-form-item label="">
          <el-button type="primary" :loading="state.loading" @click="searchFormActions.onSearch"
            >查询</el-button
          >
          <el-button @click="searchFormActions.resetFields(searchFormRef)">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="middle-content p-4">
      <div class="tools mb-4">
        <div class="toolBtns">
          <el-button type="primary" @click="tableActions.create" :disabled="ifSubManager">
            <PlusOutlined />新建
          </el-button>
          <!-- <el-button :loading="state.loading" @click="tableActions.importOrg" v-if="appAutoFlag != 1">
            <DownloadOutlined />导入
          </el-button> -->
          <el-popconfirm
            title="确定要删除吗？"
            @confirm="tableActions.batchDel"
            confirm-button-text="确定"
            cancel-button-text="取消"
          >
            <template #reference>
              <el-button link :disabled="table.selected.length == 0 || ifSubManager">
                <Icon icon="ep:delete" />批量删除
              </el-button>
            </template>
          </el-popconfirm>
        </div>
        <div class="selected">
          已选择<span class="blue">{{ table.selected.length }} 项</span>
        </div>
      </div>
      <el-table
        ref="lazyTableRef"
        class="mb-4"
        v-loading="state.loading"
        :data="tableData"
        @selection-change="tableActions.selectionChange"
        row-key="id"
        lazy
        :load="tableActions.load"
        :header-cell-style="{ background: '#f1f3f7' }"
      >
        <el-table-column type="selection" width="55" fixed />
        <el-table-column prop="orgName" label="机构名称" fixed show-overflow-tooltip />
        <el-table-column prop="orgNo" label="机构编号" fixed show-overflow-tooltip />
        <el-table-column prop="createBy" label="创建人" />
        <el-table-column prop="operation" label="操作" :width="260" fixed="right">
          <template #default="scope">
            <el-button
              link
              type="primary"
              @click="tableActions.update(scope.row)"
              :disabled="scope.row.autoFlag == 1 || ifSubManager"
              >编辑
            </el-button>
            <el-popconfirm
              title="确定要删除吗？"
              @confirm="tableActions.delete(scope.row)"
              confirm-button-text="确定"
              cancel-button-text="取消"
            >
              <template #reference>
                <el-button link type="danger" :disabled="scope.row.autoFlag == 1 || ifSubManager"
                  >删除</el-button
                >
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        class="flex justify-end"
        background
        layout="total, sizes, prev, pager, next"
        :total="pg.total"
        :current-page="pg.current"
        v-model:page-size="pg.size"
        @size-change="pgActions.sizeChange"
        @current-change="pgActions.currentChange"
        :page-sizes="[20, 30, 50]"
      />
    </div>
    <AddOrgModal
      v-model:visible="modal.visible"
      :data="modal.data"
      :menuList="tableData"
      @success="modalActions.success"
      @getParentId="modalActions.getParentId"
      @getUpdateMode="modalActions.getUpdateMode"
    />
    <PickOrgModal
      v-model:visible="pickOrgModal.visible"
      :orgTreeData="tableData"
      @success="pickOrgModalActions.success"
    />
  </div>
</template>

<style lang="less" scoped>
  html[data-theme='light'] {
    .searchBox,
    .middle-content {
      background-color: #fff;
    }
  }

  html[data-theme='dark'] {
    .searchBox,
    .middle-content {
      background-color: #151515;
    }
  }

  .menu-management {
    min-height: 100%;
    display: flex;
    flex-direction: column;

    .middle-content {
      flex: 1;

      .tools {
        display: flex;
        justify-content: space-between;

        .selected {
          line-height: 32px;

          .blue {
            margin-left: 5px;
            color: #237ae4;
          }
        }
      }
    }
  }
</style>
